﻿using Common.Communication;
using DeviceBase.Enums;
using DeviceBase.Interfaces;
using DeviceBase.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace JueYuanNaiYa.Core.AnBai
{
    public class AT686SerialPort : SerialPortBase, IJueYuanNaiYa
    {
        public string Name { get; set; }
        public AT686SerialPort(string name, string portName, int baudRate = 115200, int timeout = 1000) : base(portName, baudRate, timeout: timeout)
        {
            Name = name;
        }
        public Result<bool> NewTest(int steps)
        {
            Result<bool> result = new Result<bool>();
            AppendInfo(Name, $"新增测试方案");
            var command = CmdNew;
            var re = Write(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "新增测试方案失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetStep;
            var re1 = WriteThenRead(command);
            if (!re1.IsSucceed || !re1.Value.Contains(CmdNewOk))
            {
                result.IsSucceed = false;
                result.Err = "新增测试方案失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, "新增测试方案成功");
            return result.EndTime();
        }

        public Result<bool> SetBeep(bool isOn)
        {
            Result<bool> result = new Result<bool>();
            AppendInfo(Name, $"设置蜂鸣器{isOn}");
            var command = CmdSetBeep(isOn ? "ON" : "OFF");
            var re = WriteThenRead(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置蜂鸣器失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetBeep;
            //发送指令并返回
            var re2 = WriteThenRead(command);
            if (!re2.IsSucceed || !re2.Value.Contains(isOn ? "ON" : "OFF"))
            {
                result.IsSucceed = false;
                result.Err = "设置蜂鸣器失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, "设置蜂鸣器成功");
            return result.EndTime();
        }

        public Result<bool> SetTest(JueYuanNaiYaEnum.JueYuanNaiYaMode mode, int step, double vol, double upTime, double downTime, double keepTime, double min, double max, int freq = 0, double arc = 0)
        {
            Result<bool> result = new Result<bool>();
            AppendInfo(Name, $"设置测试参数");
            AppendInfo(Name, $"步骤检查{step}");
            var command = CmdGetStep;
            var re = WriteThenRead(command);
            if (!re.IsSucceed || !re.Value.Contains("TOTAL"))
            {
                result.IsSucceed = false;
                result.Err = "步骤检查失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            if (Convert.ToInt32(re.Value.Split('-')[1].Replace("TOTAL", "").Trim()) < step)
            {
                AppendInfo(Name, $"新增步骤{step}");
                command = CmdInsertStep;
                var re2 = Write(command);
                if (!re2.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "新增步骤失败";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                command = CmdGetBeep;
                //发送指令并返回
                re = WriteThenRead(command);
                if (!re.IsSucceed || !re.Value.Contains("STEP " + step + " - TOTAL " + step))
                {
                    result.IsSucceed = false;
                    result.Err = "新增步骤失败";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
            }
            string type = "";
            switch (mode)
            {
                case JueYuanNaiYaEnum.JueYuanNaiYaMode.绝缘电阻:
                    type = "IR";
                    break;
                case JueYuanNaiYaEnum.JueYuanNaiYaMode.直流耐压:
                    type = "DC";
                    break;
                case JueYuanNaiYaEnum.JueYuanNaiYaMode.交流耐压:
                    type = "AC";
                    break;
                default:
                    break;
            }
            AppendInfo(Name, $"设置测试类型{type}");
            command = CmdType(type,step);
            var re1 = Write(command);
            if (!re1.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置测试类型失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetType(step);
            //发送指令并返回
            re = WriteThenRead(command);
            if (!re.IsSucceed || !re.Value.Contains(type))
            {
                result.IsSucceed = false;
                result.Err = "设置测试类型失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            if (type == "AC")
            {
                AppendInfo(Name, $"设置频率{freq}Hz");
                command = CmdFreq(freq, step);
                re1 = Write(command);
                if (!re1.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置频率失败";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                command = CmdGetFreq(step);
                re = WriteThenRead(command);
                if (!re.IsSucceed || !int.TryParse(re.Value, out int va) || va != freq)
                {
                    result.IsSucceed = false;
                    result.Err = "设置频率失败";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置电弧{arc}A");
                command = CmdArc(arc, step);
                re1 = Write(command);
                if (!re1.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置电弧失败";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                command = CmdGetArc(step);
                re = WriteThenRead(command);
                if (!re.IsSucceed || !double.TryParse(re.Value, out double val) || val != arc)
                {
                    result.IsSucceed = false;
                    result.Err = "设置电弧失败";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
            }
            AppendInfo(Name, $"设置电压{vol}V");
            command = CmdSetVol(vol, step);
            re1 = Write(command);
            if (!re1.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置电压失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetVol(step);
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double v) || v != vol)
            {
                result.IsSucceed = false;
                result.Err = "设置电压失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置上升时间{upTime}s");
            command = CmdUpTime(upTime, step);
            re1 = Write(command);
            if (!re1.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置上升时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetUpTime(step);
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double ut) || ut != upTime)
            {
                result.IsSucceed = false;
                result.Err = "设置上升时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置保持时间{keepTime}s");
            command = CmdKeepTime(keepTime, step);
            re1 = Write(command);
            if (!re1.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置保持时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetKeepTime(step);
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double kt) || kt != keepTime)
            {
                result.IsSucceed = false;
                result.Err = "设置保持时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置下降时间{downTime}s");
            command = CmdDownTime(downTime, step);
            re1 = Write(command);
            if (!re1.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置下降时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetDownTime(step);
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double dt) || dt != downTime)
            {
                result.IsSucceed = false;
                result.Err = "设置下降时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置上限{max}");
            command = CmdMax(max, step);
            re1 = Write(command);
            if (!re1.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置上限失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetMax(step);
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double ma) || ma != max)
            {
                result.IsSucceed = false;
                result.Err = "设置上限失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置下限{min}");
            command = CmdMin(min, step);
            re1 = Write(command);
            if (!re1.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置下限失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetMin(step);
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double mi) || mi != min)
            {
                result.IsSucceed = false;
                result.Err = "设置下限失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置测试参数成功");
            return result.EndTime();
        }

        public Result<List<JueYuanNaiYaResult>> StartTest(int timeout)
        {
            Result<List<JueYuanNaiYaResult>> result = new Result<List<JueYuanNaiYaResult>>();
            AppendInfo(Name, $"开始测试");
            var command = CmdStart;
            var re = Write(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "开始测试失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            DateTime testTime = DateTime.Now.AddSeconds(timeout + 3000);
            string r = "";
            while (string.IsNullOrEmpty(r) && DateTime.Now < testTime)
            {
                var re1 = ReadString();
                //M1,ACW,Pass,0.01,0.000,5.0,1
                r = re1.Value.Trim();
                Thread.Sleep(500);
                if (DeviceBase.DeviceServer.IsStop)
                {
                    Write(CmdStop);
                    result.IsSucceed = false;
                    result.Err = "停止测试";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
            }
            //返回值为空
            if (r == "")
            {
                Write(CmdStop);
                result.IsSucceed = false;
                result.Err = "返回超时";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            // IR,0.050kV,34.59MΩ,PASS;ACW,0.050kV,0.000mA,PASS; 
            var str = r.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in str)
            {
                string[] str2 = item.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                JueYuanNaiYaResult jueYuanNai = new JueYuanNaiYaResult()
                {
                    type = str2[0],
                    value = str2[1] + "," + str2[2],
                    isPass= item.Contains("PASS"),
                };
                result.Value.Add(jueYuanNai);
                AppendResult(Name, item);
            }
            result.IsSucceed = result.Value.Count(o => o.isPass == false) == 0;
            if (!result.IsSucceed)
                re.Err = "测试未通过";
            return result.EndTime();
        }

        public Result<bool> StopTest()
        {
            Result<bool> result = new Result<bool>();
            AppendInfo(Name, $"停止测试");
            List<string> temps = new List<string>();
            var command = CmdStop;
            var re = Write(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "停止测试失败";
                AppendResult(Name, result.Err);
            }
            AppendInfo(Name, $"停止测试成功");
            return result.EndTime();
        }

        public double IrVolMin = 0.05f;
        public double IrVolMax = 1;
        public double TimeMin = 0.1f;
        public double TimeMax = 999.9f;
        public double IrMin = 0.1f;
        public double IrMax = 10000;
        public double DcwVolMin = 0.05f;
        public double DcwVolMax = 6f;
        public double DcwMin = 0.001f;
        public double DcwMax = 5;
        public double AcwVolMin = 0.05f;
        public double AcwVolMax = 1f;
        public double AcwMin = 0.0001f;
        public double AcwMax = 5;
        string Id => "*IDN?\n"; 
        string CmdNew=>":FUNC:SOUR:STEP:NEW\n"; 
        string CmdNewOk => "STEP 1 - TOTAL 1"; 
        string CmdInsertStep => ":FUNC:SOUR:STEP:INS\n";
        string CmdGetStep => ":FUNC:SOUR:STEP?\n";
        string CmdSetBeep(string beep) { return ":SYST:BEEP " + beep + "\n"; }
        string CmdGetBeep => ":SYST:BEEP?\n";   
        string CmdSetVol(double vol, int step) { return ":FUNC:SOUR:STEP" + step + ":VOLT " + vol + "\n"; }
        string CmdGetVol(int step) { return ":FUNC:SOUR:STEP" + step + ":VOLT?\n"; }
        string CmdUpTime(double upTime, int step) { return ":FUNC:SOUR:STEP" + step + ":RTIM " + upTime + "\n"; }
        string CmdGetUpTime(int step) { return ":FUNC:SOUR:STEP" + step + ":RTIM?\n"; }
        string CmdKeepTime(double keepTime, int step) { return ":FUNC:SOUR:STEP" + step + ":TTIM " + keepTime + "\n"; }
        string CmdGetKeepTime(int step) { return ":FUNC:SOUR:STEP" + step + ":TTIM?\n"; }
        string CmdDownTime(double downTime, int step) { return ":FUNC:SOUR:STEP" + step + ":FTIM " + downTime + "\n"; }
        string CmdGetDownTime(int step) { return ":FUNC:SOUR:STEP" + step + ":FTIM?\n"; }
        string CmdType(string type, int step) { return ":FUNC:SOUR:STEP" + step + ":TYPE " + type + "\n"; }
        string CmdGetType(int step) { return ":FUNC:SOUR:STEP" + step + ":TYPE?\n"; }
        string CmdFreq(int freq, int step) { return ":FUNC:SOUR:STEP" + step + ":FREQ " + freq + "\n"; }
        string CmdGetFreq(int step) { return ":FUNC:SOUR:STEP" + step + ":FREQ?\n"; }
        string CmdArc(double arc, int step) { return ":FUNC:SOUR:STEP" + step + ":ARC " + arc + "\n"; }
        string CmdGetArc(int step) { return ":FUNC:SOUR:STEP" + step + ":ARC?\n"; }
        string CmdMax(double max, int step) { return ":FUNC:SOUR:STEP" + step + ":UPPER " + max + "\n"; }
        string CmdGetMax(int step) { return ":FUNC:SOUR:STEP" + step + ":UPPER?\n"; }
        string CmdMin(double min, int step) { return ":FUNC:SOUR:STEP" + step + ":LOWER " + min + "\n"; }
        string CmdGetMin(int step) { return ":FUNC:SOUR:STEP" + step + ":LOWER?\n"; }
        string CmdStart => ":FUNC:START\n";
        string CmdStop => ":FUNC:STOP\n";
    }
}
